<?php
class ItemsController extends AppController {
    var $pageTitle = 'Barang';
    
    function add() {
        $this->__setAdditionals();
        parent::add();
    }
    
    function edit($id = null) {
        $this->__setAdditionals();
        parent::edit($id);
    }
    
    function __setAdditionals() {
        $units = $this->Item->Unit->find('list');
        $this->set('units', $units);
    }
    
    function view_stocks() {
        $this->pageTitle = 'Stok Barang';
        $items = $this->Item->find('all', array(
            'fields' => array('Item.id', 'Item.name', 'Item.code', 'Unit.name'),
            'order' => 'Item.name ASC'
        ));
        
        foreach ($items as $key => $item) {
            $items[$key]['Item']['penerimaan'] = $this->__getStockIn( $item['Item']['id'] );
            $items[$key]['Item']['pengeluaran'] = $this->__getStockOut( $item['Item']['id'] );
            $items[$key]['Item']['stok'] = $items[$key]['Item']['penerimaan'] - $items[$key]['Item']['pengeluaran'];
        }
        
        $this->set('records', $items);
    }
    
    function view_zero_stocks() {
        $this->pageTitle = 'Barang yang harus dibeli';
        $items = $this->Item->find('all', array(
            'fields' => array('Item.id', 'Item.name', 'Item.code', 'Unit.name'),
            'order' => 'Item.name ASC'
        ));
        
        foreach ($items as $key => $item) {
            $stock = $this->__getStockIn( $item['Item']['id'] ) - $this->__getStockOut( $item['Item']['id'] );
            if ( $stock > 0 ) {
                unset( $items[$key] );
                continue;
            }
        }
        
        $this->set('records', $items);
    }
    
    function miss_stocks() {
        $this->pageTitle = 'Miss Stocks';
        
        // check if data is posted
        if ( !empty($this->data) ) {
            if ( isset($this->data['items']) ) {
                foreach ($this->data['items'] as $item_id => $item_val) {
                    if ( $this->data['act'] == 'first_stock_in' ) {
                        $this->__fixItemOutBeforeStockIn($item_id, $item_val['stock_first_in']);
                    } else if ( $this->data['act'] == 'negative_stock' ) {
                        $this->__fixNegativeStock($item_id, $item_val);
                    }
                }
            }
        }
        
        $items = $this->Item->find('all', array(
            'fields' => array('Item.id', 'Item.name', 'Item.code', 'Unit.name'),
            'order' => 'Item.name ASC'
        ));
        
        if ( !class_exists('ItemOut') && !isset($this->ItemOut) ) {
            ClassRegistry::init('ItemOut');
            $this->ItemOut = new ItemOut;
        }
        
        $stock_in = $this->__getStockInFirstAndLast();
        
        foreach ($items as $key => $item) {
            $items[$key]['Item']['penerimaan'] = $this->__getStockIn( $item['Item']['id'] );
            $items[$key]['Item']['pengeluaran'] = $this->__getStockOut( $item['Item']['id'] );
            $items[$key]['Item']['stok'] = $items[$key]['Item']['penerimaan'] - $items[$key]['Item']['pengeluaran'];
            $items[$key]['Item']['stock_first_in'] = 
                isset($stock_in[ $item['Item']['id'] ]['first']) ? $stock_in[ $item['Item']['id'] ]['first'] : '';
            $items[$key]['Item']['stock_last_in'] = 
                isset($stock_in[ $item['Item']['id'] ]['last']) ? $stock_in[ $item['Item']['id'] ]['last'] : '';
            
            // item out with date_approved below stock_first_in
            $items[$key]['Item']['below_first_stock_first_in'] = array();
            if ( !empty($stock_in[ $item['Item']['id'] ]['first']) ) {
                $below_first_stock_first_in = $this->ItemOut->find('all', array(
                    'fields' => array(
                        'id', 'total_approved', 'date_approved'
                    ),
                    'conditions' => array(
                        'item_id' => $item['Item']['id'],
                        'approved' => 1,
                        'date_approved <' => $stock_in[ $item['Item']['id'] ]['first']
                    ),
                    'order' => 'date_approved ASC',
                    'recursive' => -1
                ));
                $items[$key]['Item']['below_first_stock_first_in'] = $below_first_stock_first_in;
            }
            
            // negative stock
            $items[$key]['Item']['negative_stock'] = array();
            if ( !empty($items[$key]['Item']['stock_first_in']) ) {
                $items[$key]['Item']['negative_stock'] = $this->__getNegativeStock($item['Item']['id']);
            }
            
            if ( empty($items[$key]['Item']['below_first_stock_first_in']) &&
                 empty($items[$key]['Item']['negative_stock']) ) {
            
                unset($items[$key]);
            }
        }
        
        $this->set('records', $items);
    }
    
    function __getStockOut($item_id, $periode = null) {
        ClassRegistry::init('ItemOut');
        $this->ItemOut = new ItemOut;
        return $this->ItemOut->getTotal($item_id, $periode);
    }
    
    function __getStockIn($item_id, $periode = null) {
        ClassRegistry::init('ItemIn');
        $this->ItemIn = new ItemIn;
        return $this->ItemIn->getTotal($item_id, $periode);
    }
    
    function __getStockInFirstAndLast() {
        if ( !class_exists('ItemIn') && !isset($this->ItemIn) ) {
            ClassRegistry::init('ItemIn');
            $this->ItemIn = new ItemIn;
        }
        
        $items = $this->ItemIn->find('all', array(
            'fields' => array('item_id', 'MIN(ItemIn.date_in) as first', 'MAX(ItemIn.date_in) as last'),
            'group' => 'ItemIn.item_id',
            'order' => array(
                'ItemIn.item_id ASC',
                'ItemIn.date_in ASC'
            ),
            'recursive' => -1
        ));
        
        $stocks = array();
        foreach ($items as $item) {
            $stocks[$item['ItemIn']['item_id']]['first'] = $item[0]['first'];
            $stocks[$item['ItemIn']['item_id']]['last'] = $item[0]['last'];
        }
        
        return $stocks;
    }
    
    function __getNegativeStock($item_id) {
        if ( !class_exists('ItemIn') && !isset($this->ItemIn) ) {
            ClassRegistry::init('ItemIn');
            $this->ItemIn = new ItemIn;
        }
        
        if ( !class_exists('ItemOut') && !isset($this->ItemOut) ) {
            ClassRegistry::init('ItemOut');
            $this->ItemOut = new ItemOut;
        }
        
        $item_in = $this->ItemIn->find('all', array(
            'fields' => array('item_id', 'total', 'date_in'),
            'conditions' => array(
                'item_id' => $item_id
            ),
            'order' => 'date_in ASC',
            'recursive' => -1
        ));
        
        // collect all date_in
        $date_in_of_item_in = array();
        foreach ($item_in as $item) {
            $date_in_of_item_in[] = $item['ItemIn']['date_in'];
        }
        $this->date_in_of_item_in = $date_in_of_item_in;
        
        $stock_in = array();
        $negative_stock = array();
        $stock = 0;
        foreach ($item_in as $key => $in) {
            if ( isset($stock_in[$in['ItemIn']['date_in']]) ) {
                $stock_in[$in['ItemIn']['date_in']] += $in['ItemIn']['total'];
            } else {
                $stock_in[$in['ItemIn']['date_in']] = $in['ItemIn']['total'];
            }
            $stock += $in['ItemIn']['total'];
            
            if ( isset($item_in[$key+1]) && ($in['ItemIn']['date_in'] == $item_in[$key+1]['ItemIn']['date_in']) ) {
                continue;
            } else {
                $upTo = date('Y-m-d');
                if ( isset($item_in[$key+1]) ) {
                    $upTo = $item_in[$key+1]['ItemIn']['date_in'];
                }
                $item_out = $this->ItemOut->find('all', array(
                    'fields' => array('id', 'item_id', 'total_approved', 'date_approved'),
                    'conditions' => array(
                        'item_id' => $item_id,
                        'date_approved >=' => $in['ItemIn']['date_in'],
                        'date_approved <' => $upTo
                    ),
                    'order' => 'date_approved ASC, created ASC',
                    'recursive' => -1
                ));
                
                foreach ($item_out as $idx => $out) {
                    $stock = $stock - $out['ItemOut']['total_approved'];
                    
                    // negative stock
                    if ( $stock < 0 ) {
                        if ( !isset($negative_stock[$in['ItemIn']['date_in']]) ) {
                            $negative_stock[$in['ItemIn']['date_in']] = $stock;
                        }
                        
                        // change date_approved to select
                        $out['ItemOut']['select_date_approved'] = $this->__buildDateApprovedSelect($out['ItemOut']['date_approved']);
                        
                        $negative_stock[$in['ItemIn']['date_in']] += $out['ItemOut']['total_approved'];
                        $negative_stock[] = $out['ItemOut'];
                    }
                }
            }
        }
        // get stock in after negative stock
        if ( !empty($negative_stock) ) {
            $negative_stock[$in['ItemIn']['date_in']] = $stock;
        }
        
        return $negative_stock;
    }
    
    function __buildDateApprovedSelect($first_date_approved) {
        $ret = array($first_date_approved => $first_date_approved);
        $str_first_date_approved = strtotime($first_date_approved);
        foreach ($this->date_in_of_item_in as $date_in) {
            if ( strtotime($date_in) > $str_first_date_approved) {
                $ret[$date_in] = $date_in;
            }
        }
        
        return $ret;
    }
    
    function __fixItemOutBeforeStockIn($item_id, $new_date) {
        if ( !class_exists('ItemOut') && !isset($this->ItemOut) ) {
            ClassRegistry::init('ItemOut');
            $this->ItemOut = new ItemOut;
        }
        
        return $this->ItemOut->updateAll(
            array('ItemOut.date_approved' => "'".$new_date."'"),
            array(
                'ItemOut.item_id' => $item_id,
                'ItemOut.date_approved <' => $new_date,
            )
        );
    }
    
    function __fixNegativeStock($item_out_id, $new_date) {        
        if ( !class_exists('ItemOut') && !isset($this->ItemOut) ) {
            ClassRegistry::init('ItemOut');
            $this->ItemOut = new ItemOut;
        }
        
        return $this->ItemOut->updateAll(
            array('ItemOut.date_approved' => "'".$new_date."'"),
            array(
                'ItemOut.id' => $item_out_id
            )
        );
    }
}
?>
